package org.flexthinker.module.impl
{
    import mx.events.ModuleEvent;

    import org.flexunit.async.Async;
    import org.hamcrest.assertThat;
    import org.hamcrest.object.equalTo;

    /**
     *
     */
    public class ModuleDescriptorLoaderTest
    {
        //to be used when tested from IJ IDE
//        private static const MODULE_URL:String = "test-classes/test/ButtonModule.swf";
//        private static const MODULE_SKIN_URL:String = "test-classes/test/Skin1_buttonModule.swf";

        // to the used when tested with maven
        private static const MODULE_URL:String = "test/ButtonModule.swf";
        private static const MODULE_SKIN_URL:String = "test/Skin1_buttonModule.swf";

        private var descriptor:ModuleDescriptor;
        private var styleDescriptor:StylesheetDescriptor;

        private var moduleDescriptorLoader:ModuleDescriptorLoader;

        private var progressData:Array = [];


        public function ModuleDescriptorLoaderTest()
        {
        }

        [Before]
        public function init():void
        {
            descriptor = new ModuleDescriptor(MODULE_URL);
            styleDescriptor = new StylesheetDescriptor(MODULE_SKIN_URL);

            descriptor.addDependency(styleDescriptor);

            progressData = [];
        }

        [After]
        public function tearDown():void
        {
            if (moduleDescriptorLoader)
            {
                moduleDescriptorLoader.unload();
            }
        }


        [Test(async,timeout="4000")]
        public function testModuleLoadingWithStylesheet():void
        {
            moduleDescriptorLoader = new ModuleDescriptorLoader(descriptor);

            Async.handleEvent(this, moduleDescriptorLoader, ModuleEvent.READY, readyHandler, 4000);
            moduleDescriptorLoader.addEventListener(ModuleEvent.ERROR, errorHandler);
            moduleDescriptorLoader.addEventListener(ModuleEvent.PROGRESS, progressHandler);

            assertThat("descriptors length is wrong", moduleDescriptorLoader.numDescriptors, equalTo(2));

            moduleDescriptorLoader.load();
        }

        private function readyHandler(event:ModuleEvent, param:Object):void
        {
            assertThat("Module's ready flag should have been true", moduleDescriptorLoader.ready, equalTo(true));

            testProgressData();

            var lastProgressData:Object = progressData[ progressData.length - 1 ];
            // trace(" >>>  PROGRESS " + lastProgressData.bytesLoaded + ":" + lastProgressData.bytesTotal );
            assertThat("BytesLoaded are wrong", lastProgressData.bytesLoaded > 1000000, equalTo(true));
            assertThat("BytesTotal are wrong", lastProgressData.bytesTotal > 1000000, equalTo(true));
        }

        private function testProgressData():void
        {
            var i:int = 0;
            for (i = 1; i < progressData.length; i++)
            {
                assertThat("bytes loaded should be less than bytes total",
                        progressData[i].bytesLoaded <= progressData[i].bytesTotal, equalTo(true));
                assertThat("progress went wrong", progressData[i - 1].bytesLoaded <= progressData[i].bytesTotal,
                        equalTo(true));

            }

            assertThat("bytesLoaded should be equal to bytesTotal in the end",
                    (progressData[i - 1].bytesLoaded - progressData[i - 1].bytesTotal) == 0, equalTo(true));
        }

        private function errorHandler(event:ModuleEvent):void
        {
            assertThat("module should have loaded", event.errorText, equalTo("Error is:"));
        }

        private function progressHandler(event:ModuleEvent):void
        {
            progressData.push({bytesLoaded:event.bytesLoaded, bytesTotal:event.bytesTotal });
        }

    }
}